package org.delphy.indy2.containers
{
	import flash.display.DisplayObject;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.geom.Point;
	
	import mx.core.Application;
	import mx.core.UIComponent;
	import mx.managers.PopUpManager;
	
	import org.delphy.indy2.containers.carbonWindowClasses.*;
	import org.delphy.indy2.events.CarbonWindowEvent;
	
	import caurina.transitions.Tweener;
	
	//----------------------------------
	//  Events
	//----------------------------------	
	
	/**
	 * Dispatched when the window is being closed
	 * TODO: This feature will be implemented in future release 
	 * 
	 * @eventType org.delphy.indy2.events.CarbonWindowEvent.WINDOW_CLOSE
	 */			
	[Event(name="windowClose", type="org.delphy.indy2.events.CarbonWindowEvent")]
	
	/**
	 * Dispatched before a window starts moving
	 * 
	 * @eventType org.delphy.indy2.events.CarbonWindowEvent.WINDOW_START_MOVE
	 */			
	[Event(name="windowStartMove", type="org.delphy.indy2.events.CarbonWindowEvent")]

	/**
	 * Dispatched after a window stops moving
	 * 
	 * @eventType org.delphy.indy2.events.CarbonWindowEvent.WINDOW_STOP_MOVE
	 */			
	[Event(name="windowStopMove", type="org.delphy.indy2.events.CarbonWindowEvent")]

	/**
	 * Dispatched continuously while a window is moving
	 * 
	 * @eventType org.delphy.indy2.events.CarbonWindowEvent.WINDOW_MOVING
	 */			
	[Event(name="windowMoving", type="org.delphy.indy2.events.CarbonWindowEvent")]

	//----------------------------------
	//  Styles
	//----------------------------------
	
	/**
	 * Title Bar Class
	 * Note that classes must implement ICarbonTitleBar
	 * 
	 * @default: org.delphy.indy2.containers.carbonWindowClasses.CarbonTitleBar
	 */
	[Style(name="titleBarClass", type="Class", inherit="no")]
	
	public class CarbonWindow extends CarbonPanel
	{

		//----------------------------------
		//  Constrations
		//----------------------------------	
		
		/**
		 * @public
		 */
		public static const HORIZONTAL_DIRECTION:String = "horizontal";
		
		/**
		 * @public
		 */
		public static const VERTICAL_DIRECTION:String = "vertical";

		//----------------------------------
		//  Animations
		//----------------------------------	
		
		/**
		 * @public
		 * Duration of showing/hiding windows
		 * 
		 * @defaut 1.3
		 */
		[Bindable]
		protected var _transitionTime : Number= 1.3;
		public function set transitionTime(value:Number):void{
			_transitionTime=value;
		}
		public function get transitionTime():Number{
			return _transitionTime;
		}
		
		//----------------------------------
		//  Title Bar
		//----------------------------------	
		
		/**
		 * @protected
		 * Default title bar class
		 * 
		 * @default org.delphy.indy2.containers.carbonWindowClasses.CarbonTitleBar
		 */
		protected var defaultTitleBarClass: Class = CarbonTitleBar;
		
		/**
		 * @public
		 * The title bar
		 */
		protected var _titleBar:ICarbonTitleBar;
		public function get titleBar():ICarbonTitleBar{
			return _titleBar;
		}
		
		/**
		 * @public
		 * Title bar direction, either "horizontal" or "vertical"
		 * 
		 * @default "horizontal"
		 */
		[Inspectable(category="General", enumeration="horizontal,vertical")]
		protected var _titleDirection:String = CarbonTitleBar.HORIZONTAL_DIRECTION;
		public function get titleDirection():String
		{ 
			return _titleDirection; 
		}

		public function set titleDirection(value:String):void
		{
			if (value != _titleDirection)
			{
				_titleDirection = value;
				invalidateDisplayList();
			}
		}
		
		/**
		 * @public
		 * The weight of title bar. Either the width if the direction is vertical, or the height if horizontal
		 * 
		 * @default 30
		 */ 
		private var _titleWeight:Number = 30;
		public function get titleWeight():Number
		{ 
			return _titleWeight; 
		}
		public function set titleWeight(value:Number):void
		{
			if (value != _titleWeight)
			{
				_titleWeight = value;
				invalidateDisplayList();
			}
		}
		
		/**
		 * @public
		 * 
		 * Title string
		 */
		[Bindable]
		protected var _title:String;
		public function get title():String
		{ 
			return _title; 
		}
		public function set title(value:String):void
		{
			if (value !== _title)
			{
				_title = value;
				invalidateDisplayList();
			}
		}
		
		//----------------------------------
		//  Window States
		//----------------------------------	
		
		/**
		 * @protected
		 */
		protected var isMoving:Boolean = false;
		
		/**
		 * @protected
		 */
		protected var dragStartX:Number;
		
		/**
		 * @protected
		 */
		protected var dragStartY:Number;
		
		/**
		 * @protected
		 */
		protected var startX:Number;
		
		/**
		 * @protected
		 */
		protected var startY:Number;
		
		//----------------------------------
		//  Methods
		//----------------------------------	
		
		/**
		 * Constructor
		 */		
		public function CarbonWindow()
		{
			super();
		}
		
		/**
		 * @protected
		 */
		override protected function createChildren():void{
			super.createChildren();

			// Fall to default style if no styleName is specified
			if(!styleName)
				styleName="carbonWindow";
			
			// Fall to default title bar class if not specified
			var titleBarClass: Class = getStyle("titleBarClass");
			if(!titleBarClass)
				titleBarClass = defaultTitleBarClass;
			
			_titleBar=new titleBarClass();
			UIComponent(_titleBar).addEventListener(MouseEvent.MOUSE_DOWN,onTitleMouseDown);
			rawChildren.addChild(DisplayObject(_titleBar));
		}
		
		/**
		 * @protected
		 * Built-in event handler for CarbonWindowEvent.WINDOW_CLOSE
		 * 
		 * TODO: This will be implemented in future release 
		 */
		protected function onCloseButtonClick(evt:MouseEvent):void{
			evt.stopPropagation();
			dispatchEvent(new CarbonWindowEvent(CarbonWindowEvent.WINDOW_CLOSE));

			parent.removeChild(this);
		}
		
		/**
		 * @protected
		 * Built-in event handler for CarbonWindowEvent.WINDOW_START_MOVE
		 */
		protected function onTitleMouseDown(evt:MouseEvent):void{
			systemManager.addEventListener(MouseEvent.MOUSE_UP,onTitleMouseUp,true);
			systemManager.addEventListener(MouseEvent.MOUSE_MOVE,onTitleMouseMove,true);
			
			dragStartX=evt.stageX;
			dragStartY=evt.stageY;
			startX=x;
			startY=y;
			
			isMoving=true;
			
			dispatchEvent(new CarbonWindowEvent(CarbonWindowEvent.WINDOW_START_MOVE));
		}
		
		/**
		 * @protected
		 * Built-in event handler for CarbonWindowEvent.WINDOW_STOP_MOVE
		 */
		protected function onTitleMouseUp(evt:MouseEvent):void{
			if(isMoving){
				evt.stopImmediatePropagation();
				move(startX+evt.stageX-dragStartX,startY+evt.stageY-dragStartY);
				
				systemManager.removeEventListener(MouseEvent.MOUSE_UP,onTitleMouseUp);
				systemManager.removeEventListener(MouseEvent.MOUSE_MOVE,onTitleMouseMove);
				
				isMoving=false;			
				
				dispatchEvent(new CarbonWindowEvent(CarbonWindowEvent.WINDOW_STOP_MOVE));	
			}
		}
		
		/**
		 * @protected
		 * Built-in event handler for CarbonWindowEvent.WINDOW_MOVING
		 */		
		private function onTitleMouseMove(evt:MouseEvent):void{
			if(isMoving){
				evt.stopImmediatePropagation();
				move(startX+evt.stageX-dragStartX,startY+evt.stageY-dragStartY);
				
				dispatchEvent(new CarbonWindowEvent(CarbonWindowEvent.WINDOW_MOVING));
			}
		}
		
		/**
		 * @protected
		 * 
		 * NOTE:
		 * Since Indy2 version 1.1, CarbonWindow no longer takes care of title bar positioning. Instead,
		 * it passes some necessary geometry information and let the title bar to decide for itself. 
		 * This requires that the tile bar class must implements ICarbonWindowTitleBar.
		 */
		override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void{
			super.updateDisplayList(unscaledWidth,unscaledHeight);
			
			// Reposition the title bar and the client area
			var geometry:CarbonWindowGeometry = new CarbonWindowGeometry();
			
			// Geometry of border
			geometry.topLeftRadius = _border.topLeftRadius;
			geometry.topRightRadius = _border.topRightRadius;
			geometry.bottomLeftRadius = _border.bottomLeftRadius;
			geometry.bottomRightRadius = _border.bottomRightRadius;
			geometry.borderWeight = _border.weight;
			
			// Geometry of window
			geometry.width = unscaledWidth;
			geometry.height = unscaledHeight;
			
			// Geometry of title bar
			geometry.titleBarWeight = _titleWeight;
			
			_titleBar.direction=_titleDirection;
			
			var titleBarPosition:Point = _titleBar.position(geometry);
			UIComponent(_titleBar).x = titleBarPosition.x;
			UIComponent(_titleBar).y = titleBarPosition.y;
		
			// Layout content area
			// Remember, don't set the client corner-radius to 0. Instead, always set them to a value greater than 0.
			// TODO: This bug will be fixed in future release
			if(_titleDirection == CarbonWindow.HORIZONTAL_DIRECTION){
				UIComponent(_content).x=_border.weight;
				UIComponent(_content).y=UIComponent(_titleBar).y + UIComponent(_titleBar).height;
				
				UIComponent(_content).height=UIComponent(_content).height - UIComponent(_titleBar).height;
				
				UIComponent(_content).setStyle("topLeftRadius",1);
				UIComponent(_content).setStyle("topRightRadius",1);
			}
			else if(_titleDirection == CarbonWindow.VERTICAL_DIRECTION){				
				UIComponent(_content).x=UIComponent(_titleBar).x + UIComponent(_titleBar).width;
				UIComponent(_content).y=_border.weight;
				
				UIComponent(_content).width=UIComponent(_content).width - UIComponent(_titleBar).width;
				
				UIComponent(_content).setStyle("topLeftRadius",1);
				UIComponent(_content).setStyle("bottomLeftRadius",1);
			}

		}
		
		/**
		 * @protected
		 */
		override protected function commitProperties() : void{
			super.commitProperties();
			
			if(_titleBar)
				_titleBar.title = _title;
		}
		
		/**
		 * @public
		 * Popup the window using PopUpManager
		 */
		public function popUp(center:Boolean=true):void{
			
			if(Tweener.isTweening(this)){
				return;
			}
						
			alpha=0;
			PopUpManager.addPopUp(this,DisplayObject(Application.application),false);
			if(center){
				PopUpManager.centerPopUp(this);
			}	
			
			Tweener.addTween(this,{alpha:1,time:transitionTime});			
		}
		
		/**
		 * @public
		 * Close the window and play a closing animation
		 */
		public function close():void{
			Tweener.addTween(this,{alpha:0,time:transitionTime,onComplete:onCloseAnimationComplete});
		}
		
		/**
		 * @protected
		 * Event handler for closing animation finished. We will remove the window here
		 */
		private function onCloseAnimationComplete():void{
			PopUpManager.removePopUp(this);
		}
		
		//----------------------------------
		//  Implementation of ICarbonComponent
		//----------------------------------	
		
		/**
		 * @public
		 */
		override public function get defaultStyleName() : String{
			return "carbonWindow";
		}
		
	}
}